#ifndef OBUINFO_H
#define OBUINFO_H

#include <QObject>
#include <QDateTime>

/*!
 \brief
 系统信息文件，结构定义参考：
 - 《山东省高速公路不停车收费项目卡片结构设计说明书》
 - 《GBT_28420-2012_电子收费_OBE-SAM数据格式和技术要求》
 - 《GBT_20851.4-2007_电子收费_专用短程通信_第4部分：设备应用》
*/
#pragma pack(push, 1)
struct RawObuSysInfoFile
{
    quint8 contractProvider[8];             /*!< 服务提供商名称 */
    quint8 contractType;                    /*!< 协约类型 */
    quint8 contractVersion;                 /*!< 合同版本 */
    quint8 contractSerialNumber[8];         /*!< 合同序列号 */
    quint8 contractSignedDate[4];           /*!< 合同签署日期 */
    quint8 contractExpiredDate[4];          /*!< 合同过期日期 */
    quint8 tamperStatus;                    /*!< 拆卸状态，按GBT_28420-2012，5.2.1，高4位0表示由路侧根据防拆信息控制OBU的通行，低4位为1表示正常工作状态，但已被拆过的电子标签低4位也为1 */
    quint8 vehicleLicencePlateNumber[12];   /*!< 车牌号 - 山东扩展 */
    quint8 vehicleLicencePlateColor[2];     /*!< 车牌颜色 - 山东扩展 */
    quint8 reserved[58];                    /*!< 预留 */
};
#pragma pack(pop)

/*!
 \brief
 OBU配置信息内容，长度为7字节，定义见：
 - 《GBT_28421-2012_电子收费_基于专用短程通信的电子收费交易》：有iccType的详细定义
 - 《GBT_20851.3-2007_电子收费_专用短程通信_第3部分_应用层》附录A.2。
*/
#pragma pack(push, 1)
struct RawObuConfiguration
{
    quint32 macID;                          /*!< MAC地址，同时作为LID */
    quint8  equipmentClassAndVersion;       /*!< 高4字节表示是否支持IC卡接口，0为不支持，1为支持IC卡 */
    quint8  obuStatus;                      /*!< 按位表示iccPresent(1), iccType(3), iccStatus(1), locked(1), tampered(1), battery(1)，0为正常 */
    quint8  reservedBits;
};
#pragma pack(pop)

class ObuInfo : public QObject
{

public:
    explicit ObuInfo(QObject *parent = 0);
    ObuInfo(const ObuInfo &obuInfo) : QObject(obuInfo.parent())
    {
        *this = obuInfo;
    }

    void operator =(const ObuInfo &obuInfo)
    {
        m_rawSysInfoFile=obuInfo.m_rawSysInfoFile;
        m_rawCfg=obuInfo.m_rawCfg;
        memcpy(&m_cipheredVehInfo, &obuInfo.m_cipheredVehInfo, sizeof(m_cipheredVehInfo));
        memcpy(&m_decipheredVehInfo, &obuInfo.m_decipheredVehInfo, sizeof(m_decipheredVehInfo));
        m_contractSignedDate=obuInfo.m_contractSignedDate;
        m_contractExpiredDate=obuInfo.m_contractExpiredDate;
        m_vehicleLicencePlateNumber=obuInfo.m_vehicleLicencePlateNumber;
        m_vehicleLicencePlateColor=obuInfo.m_vehicleLicencePlateColor;
    }

    bool isSame(const ObuInfo &another) const
    {
        return 0==memcmp(&m_rawSysInfoFile, &another.m_rawSysInfoFile, SYSFILE_SIZE);
    }

public:
    const static quint8 MIN_SYSFILE_SIZE=26;
    const static quint8 MAX_SYSFILE_SIZE=99;
    const static quint8 SYSFILE_SIZE=41;
    const static quint8 OBU_CFG_SIZE=7;
    const static quint8 VEH_INFO_FILE_SIZE=16;

public:
    /*!
     \brief
     设置OBU信息。
     \param sysInfo
     系统信息文件。
     \param sizeOfSysInfo
     系统信息文件长度。
     \param obuCfg
     OBU配置信息内容，长度为7字节。
     \return
     执行结果，true表示成功。
    */
    bool setObuInfo(const quint8 *sysInfo, quint8 sizeOfSysInfo, const quint8 *obuCfg);

    /*!
     * \brief setObuInfo测试辅助函数
     * \param sysInfo
     * \param obuCfg
     * \return 执行结果，true表示成功。
     */
    bool setObuInfo(const QString &sysInfo, const QString &obuCfg);

    /*!
     * \brief 保存加密车辆信息。
     * \param 加密车辆信息。
     * \param 加密数据长度。
     * \return
     */
    bool setCipheredVehInfoFile(const quint8 *vehInfoFile, quint8 fileLen);

    bool setDecipheredVehInfoFile(const quint8 *vehInfoFile, quint8 fileLen);

    /*!
     * \brief DELIVERY KEY。参《收费公路联网电子不停车收费技术要求》2.6.2.4
     * \return
     */
    quint8 *getDeliveryKeyCmdForEncrypt() const;

    /*!
     * \brief Cipher Data。参《收费公路联网电子不停车收费技术要求》2.6.2.2
     * \return
     */
    quint8 *getDecipherDataCmd() const;

    /*!
     * \brief 获取MAC地址。
     * \return MAC地址，转换为本地字节序。
     */
    quint32 getMacId() const;

    /*!
     * \brief 获取是否被拆卸。
     * \return true表示已被拆卸。
     */
    bool getTampered() const;

    /*!
     * \brief 获取是否已被锁。
     * \return true表示已被锁。
     */
    bool getLocked() const;

    /*!
     * \brief 获取是否插有可用的卡片，要求卡片已插入、状态正常、卡片类型被支持。
     * \return true表示有。
     */
    bool hasCpuCard() const;

    /*!
     * \brief 获取是否为山东发行的电子标签
     * \return true表示是。
     */
    bool isFromShandong() const;

    /*!
     * \brief 获取合同序列号。
     */
    QString getContractSN() const;

    /*!
     * \brief 获取合同签署日期。
     */
    QDate getSignedDate() const;

    /*!
     * \brief 获取合同过期日期。
     */
    QDate getExpiredDate() const;

    /*!
     * \brief 获取车牌号。
     */
    QString getVehicleLicencePlateNumber() const;

    /*!
     * \brief 获取带颜色的全车牌，如"蓝鲁A12345"。
     */
    QString getVehicleLicencePlateColorAndNumber() const;

    /*!
     * \brief 获取车牌颜色。
     */
    quint16 getVehicleLicencePlateColor() const;

protected:
    void setVehPlateNumber(quint8 *pPlate, int nLen);
    void setVehPlateColor(quint8 bHi, quint8 bLo);

protected:
    /*!
     * \brief 系统信息文件
     */
    RawObuSysInfoFile m_rawSysInfoFile;

    /*!
     * \brief OBU配置信息内容
     */
    RawObuConfiguration m_rawCfg;

    /*!
     * \brief 加密车辆信息文件
     */
    quint8 m_cipheredVehInfo[256];

    /*!
     * \brief 车辆信息文件
     */
    quint8 m_decipheredVehInfo[32];

    /*!
     * \brief 合同签署日期
     */
    QDate m_contractSignedDate;

    /*!
     * \brief 合同过期日期
     */
    QDate m_contractExpiredDate;

    /*!
     * \brief 车牌
     */
    QString m_vehicleLicencePlateNumber;

    /*!
     * \brief 车牌颜色(整型)
     */
    quint16 m_vehicleLicencePlateColor;
};
Q_DECLARE_METATYPE(ObuInfo)

#endif // OBUINFO_H
